import { exec } from 'child_process';
import { promisify } from 'util';
import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';
import { Environment } from './environmentDetector';
import { PlatformHelper } from './platformHelper';

const execAsync = promisify(exec);
const fsPromises = fs.promises;

/**
 * 容器配置接口
 */
export interface ContainerConfig {
    name: string;
    port: number;
    configPath: string;
    instances?: number;
}

/**
 * 容器状态
 */
export interface ContainerStatus {
    id?: string;
    name: string;
    state: 'running' | 'stopped' | 'error';
    ports?: string[];
    startTime?: string;
}

/**
 * 容器管理器类 - 负责容器的生命周期管理
 */
export class ContainerManager {
    private environment: Environment;
    private containers: Map<string, ContainerStatus>;
    private statusChangeEmitter: vscode.EventEmitter<ContainerStatus>;
    private platformHelper: PlatformHelper;

    constructor(environment: Environment) {
        this.environment = environment;
        this.containers = new Map();
        this.statusChangeEmitter = new vscode.EventEmitter<ContainerStatus>();
        this.platformHelper = PlatformHelper.getInstance();
    }

    /**
     * 获取容器状态变化事件
     */
    get onStatusChange(): vscode.Event<ContainerStatus> {
        return this.statusChangeEmitter.event;
    }

    /**
     * 启动Nginx容器
     */
    async startContainer(config: ContainerConfig): Promise<ContainerStatus> {
        const { name, port, configPath } = config;
        
        try {
            // 检查端口权限并提示用户（如果需要）
            if (this.platformHelper.isPrivilegedPort(port)) {
                await this.platformHelper.showPortPermissionGuide(port);
            }
            
            // 检查配置文件是否存在
            await this.validateConfigFile(configPath);
            
            // 检查并停止任何已经运行的同名容器
            await this.stopContainerByName(name);
            
            let command: string;
            let containerStatus: ContainerStatus;
            
            // 根据环境选择不同的启动命令
            if (this.environment.type === 'podman') {
                command = await this.buildPodmanCommand(name, port, configPath);
                containerStatus = await this.executeStartCommand(command, name);
            } else if (this.environment.type === 'docker') {
                command = await this.buildDockerCommand(name, port, configPath);
                containerStatus = await this.executeStartCommand(command, name);
            } else {
                throw new Error('No supported container runtime available');
            }
            
            // 保存容器状态
            this.containers.set(name, containerStatus);
            this.statusChangeEmitter.fire(containerStatus);
            
            return containerStatus;
        } catch (error) {
            const errorStatus: ContainerStatus = {
                name,
                state: 'error'
            };
            this.statusChangeEmitter.fire(errorStatus);
            throw error;
        }
    }

    /**
     * 停止容器
     */
    async stopContainer(name: string): Promise<ContainerStatus> {
        try {
            await this.stopContainerByName(name);
            
            const stoppedStatus: ContainerStatus = {
                name,
                state: 'stopped'
            };
            
            this.containers.set(name, stoppedStatus);
            this.statusChangeEmitter.fire(stoppedStatus);
            
            return stoppedStatus;
        } catch (error) {
            console.error(`Failed to stop container ${name}:`, error);
            throw new Error(`Failed to stop container ${name}: ${error instanceof Error ? error.message : String(error)}`);
        }
    }

    /**
     * 重启容器
     */
    async restartContainer(name: string): Promise<ContainerStatus> {
        try {
            const container = this.containers.get(name);
            if (!container) {
                throw new Error(`Container ${name} not found`);
            }
            
            let command: string;
            
            // 获取平台特定的命令选项
            const podmanOptions = this.platformHelper.getContainerOptions('podman');
            const dockerOptions = this.platformHelper.getContainerOptions('docker');
            
            if (this.environment.type === 'podman') {
                command = `podman ${Object.values(podmanOptions).join(' ')} restart ${name}`;
            } else if (this.environment.type === 'docker') {
                command = `docker ${Object.values(dockerOptions).join(' ')} restart ${name}`;
            } else {
                throw new Error('No supported container runtime available');
            }
            
            await execAsync(command);
            
            // 更新容器状态
            const updatedStatus = await this.getContainerStatus(name);
            this.containers.set(name, updatedStatus);
            this.statusChangeEmitter.fire(updatedStatus);
            
            return updatedStatus;
        } catch (error) {
            console.error(`Failed to restart container ${name}:`, error);
            throw new Error(`Failed to restart container ${name}: ${error instanceof Error ? error.message : String(error)}`);
        }
    }

    /**
     * 获取所有容器状态
     */
    async getAllContainers(): Promise<ContainerStatus[]> {
        try {
            let command: string;
            
            // 获取平台特定的命令选项
            const podmanOptions = this.platformHelper.getContainerOptions('podman');
            const dockerOptions = this.platformHelper.getContainerOptions('docker');
            
            if (this.environment.type === 'podman') {
                command = `podman ${Object.values(podmanOptions).join(' ')} ps -a --format "{{.ID}}|{{.Names}}|{{.Status}}|{{.Ports}}"`;
            } else if (this.environment.type === 'docker') {
                command = `docker ${Object.values(dockerOptions).join(' ')} ps -a --format "{{.ID}}|{{.Names}}|{{.Status}}|{{.Ports}}"`;
            } else {
                return Array.from(this.containers.values());
            }
            
            const { stdout } = await execAsync(command);
            const lines = stdout.trim().split('\n');
            
            const containerStatuses: ContainerStatus[] = [];
            
            for (const line of lines) {
                if (!line.trim()) continue;
                
                const [id, name, status, ports] = line.split('|');
                
                const containerStatus: ContainerStatus = {
                    id,
                    name,
                    state: status.toLowerCase().includes('up') ? 'running' : 'stopped',
                    ports: ports ? ports.split(',').map(p => p.trim()) : []
                };
                
                // 更新本地缓存
                this.containers.set(name, containerStatus);
                containerStatuses.push(containerStatus);
            }
            
            return containerStatuses;
        } catch (error) {
            console.error('Failed to get container list:', error);
            return Array.from(this.containers.values());
        }
    }

    /**
     * 热重载Nginx配置
     */
    async reloadConfig(name: string): Promise<boolean> {
        try {
            // 检查容器是否运行
            const container = await this.getContainerStatus(name);
            if (container.state !== 'running') {
                throw new Error(`Container ${name} is not running`);
            }
            
            let command: string;
            
            // 获取平台特定的命令选项
            const podmanOptions = this.platformHelper.getContainerOptions('podman');
            const dockerOptions = this.platformHelper.getContainerOptions('docker');
            
            if (this.environment.type === 'podman') {
                command = `podman ${Object.values(podmanOptions).join(' ')} exec ${name} nginx -s reload`;
            } else if (this.environment.type === 'docker') {
                command = `docker ${Object.values(dockerOptions).join(' ')} exec ${name} nginx -s reload`;
            } else {
                throw new Error('No supported container runtime available');
            }
            
            await execAsync(command);
            return true;
        } catch (error) {
            console.error(`Failed to reload configuration for ${name}:`, error);
            throw new Error(`Failed to reload configuration: ${error instanceof Error ? error.message : String(error)}`);
        }
    }

    /**
     * 验证Nginx配置文件语法
     */
    async validateConfig(configPath: string): Promise<string> {
        try {
            const tempContainerName = `nginx-syntax-check-${Date.now()}`;
            
            // 转换路径为容器可用的路径格式
            const containerConfigPath = await this.platformHelper.convertPathForContainer(configPath);
            
            let command: string;
            
            // 获取平台特定的命令选项
            const podmanOptions = this.platformHelper.getContainerOptions('podman');
            const dockerOptions = this.platformHelper.getContainerOptions('docker');
            
            if (this.environment.type === 'podman') {
                command = `podman ${Object.values(podmanOptions).join(' ')} run --name ${tempContainerName} -v "${containerConfigPath}:/etc/nginx/conf.d/default.conf" nginx:alpine nginx -t`;
            } else if (this.environment.type === 'docker') {
                command = `docker ${Object.values(dockerOptions).join(' ')} run --name ${tempContainerName} -v "${containerConfigPath}:/etc/nginx/conf.d/default.conf" nginx:alpine nginx -t`;
            } else {
                throw new Error('No supported container runtime available');
            }
            
            const { stdout } = await execAsync(command);
            
            // 清理临时容器
            if (this.environment.type === 'podman') {
                await execAsync(`podman ${Object.values(podmanOptions).join(' ')} rm ${tempContainerName}`);
            } else if (this.environment.type === 'docker') {
                await execAsync(`docker ${Object.values(dockerOptions).join(' ')} rm ${tempContainerName}`);
            }
            
            return stdout;
        } catch (error) {
            console.error('Config validation failed:', error);
            if (error instanceof Error) {
                return `Configuration test failed: ${error.message}`;
            }
            return `Configuration test failed: ${error}`;
        }
    }

    /**
     * 验证配置文件是否存在
     */
    private async validateConfigFile(configPath: string): Promise<void> {
        try {
            await fsPromises.access(configPath, fs.constants.F_OK);
        } catch (error) {
            throw new Error(`Configuration file not found at ${configPath}`);
        }
    }

    /**
     * 构建Podman启动命令
     */
    private async buildPodmanCommand(name: string, port: number, configPath: string): Promise<string> {
        // 转换路径为容器可用的路径格式
        const containerConfigPath = await this.platformHelper.convertPathForContainer(configPath);
        
        // 获取平台特定的命令选项
        const options = this.platformHelper.getContainerOptions('podman');
        const optionsStr = Object.values(options).join(' ');
        
        return `podman ${optionsStr} run -d --name ${name} -p ${port}:80 -v "${containerConfigPath}:/etc/nginx/conf.d/default.conf" nginx:alpine`;
    }

    /**
     * 构建Docker启动命令
     */
    private async buildDockerCommand(name: string, port: number, configPath: string): Promise<string> {
        // 转换路径为容器可用的路径格式
        const containerConfigPath = await this.platformHelper.convertPathForContainer(configPath);
        
        // 获取平台特定的命令选项
        const options = this.platformHelper.getContainerOptions('docker');
        const optionsStr = Object.values(options).join(' ');
        
        return `docker ${optionsStr} run -d --name ${name} -p ${port}:80 -v "${containerConfigPath}:/etc/nginx/conf.d/default.conf" nginx:alpine`;
    }

    /**
     * 执行启动命令并获取容器状态
     */
    private async executeStartCommand(command: string, name: string): Promise<ContainerStatus> {
        try {
            const { stdout } = await execAsync(command);
            const containerId = stdout.trim();
            
            // 获取启动后的容器状态
            const status = await this.getContainerStatus(name);
            
            if (status.state !== 'running') {
                throw new Error(`Container ${name} failed to start`);
            }
            
            return status;
        } catch (error) {
            console.error(`Failed to start container ${name}:`, error);
            throw new Error(`Failed to start container ${name}: ${error instanceof Error ? error.message : String(error)}`);
        }
    }

    /**
     * 停止并删除容器（如果存在）
     */
    private async stopContainerByName(name: string): Promise<void> {
        try {
            const containers = await this.getAllContainers();
            const existingContainer = containers.find(c => c.name === name);
            
            if (!existingContainer) {
                return; // 容器不存在，不需要停止
            }
            
            // 获取平台特定的命令选项
            const podmanOptions = this.platformHelper.getContainerOptions('podman');
            const dockerOptions = this.platformHelper.getContainerOptions('docker');
            
            // 停止并删除容器
            if (this.environment.type === 'podman') {
                await execAsync(`podman ${Object.values(podmanOptions).join(' ')} stop ${name}`);
                await execAsync(`podman ${Object.values(podmanOptions).join(' ')} rm ${name}`);
            } else if (this.environment.type === 'docker') {
                await execAsync(`docker ${Object.values(dockerOptions).join(' ')} stop ${name}`);
                await execAsync(`docker ${Object.values(dockerOptions).join(' ')} rm ${name}`);
            }
        } catch (error) {
            // 忽略删除不存在容器的错误
            if (error instanceof Error && !error.message.includes('No such container')) {
                throw error;
            }
        }
    }

    /**
     * 获取容器状态
     */
    private async getContainerStatus(name: string): Promise<ContainerStatus> {
        try {
            // 获取平台特定的命令选项
            const podmanOptions = this.platformHelper.getContainerOptions('podman');
            const dockerOptions = this.platformHelper.getContainerOptions('docker');
            
            let command: string;
            
            if (this.environment.type === 'podman') {
                command = `podman ${Object.values(podmanOptions).join(' ')} inspect --format '{{.ID}}|{{.State.Status}}|{{.NetworkSettings.Ports}}|{{.State.StartedAt}}' ${name}`;
            } else if (this.environment.type === 'docker') {
                command = `docker ${Object.values(dockerOptions).join(' ')} inspect --format '{{.Id}}|{{.State.Status}}|{{json .NetworkSettings.Ports}}|{{.State.StartedAt}}' ${name}`;
            } else {
                throw new Error('No supported container runtime available');
            }
            
            const { stdout } = await execAsync(command);
            const [id, status, portsJson, startTime] = stdout.trim().split('|');
            
            // 解析端口映射
            let ports: string[] = [];
            try {
                if (portsJson && portsJson !== '<nil>') {
                    // 处理 Docker 和 Podman 返回的不同格式
                    if (portsJson.startsWith('{')) {
                        const portsObj = JSON.parse(portsJson);
                        ports = Object.entries(portsObj).map(([containerPort, hostBindings]) => {
                            if (Array.isArray(hostBindings) && hostBindings.length > 0) {
                                return `${hostBindings[0].HostIp || '0.0.0.0'}:${hostBindings[0].HostPort}->${containerPort}`;
                            }
                            return containerPort;
                        });
                    } else {
                        // Podman 格式处理
                        ports = portsJson.split(' ').filter(Boolean);
                    }
                }
            } catch (error) {
                console.error('Failed to parse port information:', error);
            }
            
            const containerStatus: ContainerStatus = {
                id,
                name,
                state: status.toLowerCase() === 'running' ? 'running' : 'stopped',
                ports,
                startTime: startTime !== '<nil>' ? startTime : undefined
            };
            
            return containerStatus;
        } catch (error) {
            console.error(`Failed to get container status for ${name}:`, error);
            return {
                name,
                state: 'error'
            };
        }
    }
} 